/**
 * 声明
 */

import ButtonMenu from 'menu/button/button'
import Rte from '../editor'
import { ReactiveInstance } from './reactive'

export interface ObjectData {
  [propName: string]: string | number | boolean | null
}

export interface StringObject {
  [propName: string]: string
}

export interface HTMLAstTag {
  /** 标签名/元素名 */
  tag: string
  /** 节点注册名 */
  ref: string
  /** 普通的 attribute */
  attrs?: StringObject
  /** 双向绑定的 attribute */
  bind?: StringObject
  /** 双向绑定的 bool 类型值的 attribute */
  bool?: StringObject
  /** 双向绑定的 style attribute */
  style?: StringObject
  /** 双向绑定的 class attribute */
  classList: StringObject
  /** 事件绑定 */
  event?: StringObject
  /** 子节点树 */
  children?: HTMLAst
}

export interface HTMLAstText {
  tag: '#text'
  /** 内容/模板 */
  data: string
  /** 内容是否需要进行双向绑定 */
  bind: boolean
}

export type HTMLAst = (HTMLAstText | HTMLAstTag)[]

export interface Refs {
  [propName: string]: HTMLElement
}

/**
 * 数据顺序对应 CSSStyleDeclaration.setProperty 的参数
 * @see https://developer.mozilla.org/zh-CN/docs/Web/API/CSSStyleDeclaration/setProperty
 */
// [name, value, important]
export type InterimSet = [string, string | number | null, boolean?]

export type InterimSets = InterimSet[]

export interface ElementListenerArgument<E> {
  ev: Event
  ctx: E
  target: HTMLElement
}

export type ElementListenerThis = Rte | ButtonMenu | object

export type ElementListenerCallback<E extends ElementListenerThis> = (this: E, arg: ElementListenerArgument<E>) => void

export interface ElementListener<E extends ElementListenerThis> {
  [propName: string]: ElementListenerCallback<E>
}

export interface RenderInst {
  $data?: ReactiveInstance<any>
  $refs?: Refs
  $listener?: ElementListener<any>
}
